package com.thinkwide.data.mvc.test;

import com.thinkwide.data.mvc.annotation.MFRequestParamAttr;
import com.thinkwide.data.mvc.config.MFMappingItem;
import com.thinkwide.data.mvc.config.MFXParam;
import com.thinkwide.data.ormapping.MFReflect;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.annotation.Annotation;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class test {

    public static void main(String[] arg) throws Throwable {

        Class<?> c = Class.forName("com.thinkwide.data.mvc.test.TestController");

        Object obj = c.newInstance();
        //prepareProperty(c,obj);
        String methodName = "testLogin3";
        List<Class> list = new ArrayList<Class>();
        list.add(User.class);
        Class[] array = new Class[list.size()];
        Method method = c.getDeclaredMethod(methodName, (Class[]) list.toArray(array));
        method.setAccessible(true);
        List<Object> params = new ArrayList<Object>();
        Class<?> x = Class.forName("com.thinkwide.data.mvc.test.User");

        Object u = x.newInstance();
        MFReflect.setProperty(u, "name", "123");
        params.add(u);

        Object value = method.invoke(obj, params.toArray());

        //List<String> list=MFClassFind.getClassList("mf.mvc.test.*");

        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get("mf.mvc.test.TestController");//(clazz.getName());


        Class clazz = TestController.class;
        getParamName(clazz, "testLogin");
        //getList();
    }

    public static MFMappingItem getParamName(Class clazz, String method) throws ClassNotFoundException {
        try {
            MFMappingItem pItem = new MFMappingItem();

            ClassPool pool = ClassPool.getDefault();
            CtClass cc = pool.get(clazz.getName());
            CtMethod cm = cc.getDeclaredMethod(method);

            //方法相关

            System.out.println("方法名：" + cm.getName());
            pItem.setClassName(clazz.getName());
            pItem.setMethodName(cm.getName());

            MethodInfo methodInfo = cm.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
            }
            ;

            AnnotationsAttribute atrr = (AnnotationsAttribute) methodInfo.getAttribute(AnnotationsAttribute.visibleTag);
            String url = "";
            if (atrr.length() > 0) {
                Annotation annotation = atrr.getAnnotations()[0];
                url = annotation.getMemberValue("value").toString();

                System.out.println(annotation.getTypeName());
                System.out.println(annotation.getMemberValue("value"));
            }

            pItem.setUrl(url);

            //方法相关

            //参数相关

            CtClass[] parameterTypes = cm.getParameterTypes();

            Object[][] list = cm.getParameterAnnotations();

            String[] paramNames = new String[cm.getParameterTypes().length];

            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
            for (int i = 0; i < paramNames.length; i++) {
                paramNames[i] = attr.variableName(i + pos);
            }
            // paramNames即参数名
            for (int i = 0; i < paramNames.length; i++) {
                MFXParam param = new MFXParam();
                param.setParamName(paramNames[i]);
                param.setParamType(parameterTypes[i].getName());
                if (list[i].length > 0 && list[i][0] instanceof MFRequestParamAttr) {
                    MFRequestParamAttr ParamAttr = (MFRequestParamAttr) list[0][0];
                    System.out.println(ParamAttr.value());
                    param.setRequired(ParamAttr.required());
                    param.setValue(ParamAttr.value());
                    param.setDefaultValue(ParamAttr.defaultValue());
                }
                System.out.println(parameterTypes[i].getName());

                System.out.println(paramNames[i]);

                pItem.getParams().add(param);

            }

            return pItem;
            //参数相关
        } catch (NotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void getList() throws NotFoundException {
        ClassPool pool = ClassPool.getDefault();

        Class clz = TestController.class;

        CtClass ctClass = pool.get(clz.getName());

        Method[] methods = clz.getDeclaredMethods();

        for (Method m : methods) {
            String name = m.getName();
            CtMethod cm = ctClass.getDeclaredMethod(name);
            MethodInfo methodInfo = cm.getMethodInfo();
            Class[] parameterTypes = m.getParameterTypes();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                // exception
            }

            if (cm.getMethodInfo().getAccessFlags() != AccessFlag.PUBLIC) {
                continue;
            }

            String[] paramNames = new String[cm.getParameterTypes().length];
            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;

            for (int j = 0; j < paramNames.length; j++) {
                paramNames[j] = attr.variableName(j + pos);
            }

            System.out.printf("\"%s\":\r\n\tReturn:%s\t(Parameters ",
                    name, m.getReturnType().getSimpleName());

            for (int i1 = 0; i1 < paramNames.length; i1++) {

                System.out.printf("%d:[%s %s] ", i1 + 1, parameterTypes[i1].getSimpleName(), paramNames[i1]);
            }
            // for (Class class1 : parameterTypes) {
            // System.out.printf("[%s],", class1.getName());
            // }
            System.out.println(")\r\n");
        }
    }
}
